package com.lh.lock;

import lombok.Builder;
import lombok.Data;

import java.util.concurrent.*;

/**
 * CompletableFuture 是Future的功能增强
 * 优点:
 * 弥补了 FutureTake的缺点，更方便
 */
public class MyCompletableFuture {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        MyThreadPool threadPool = new MyThreadPool();
        ThreadPoolExecutor executor = threadPool.getExecutor();

        future01(executor);

        future02(executor);


    }

    private static void future02(ThreadPoolExecutor executor) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                    return "Hello World!";
                }, executor)
                .whenComplete((v, e) -> {
                    if (e == null) {
                        System.out.println("计算完成,并未发生异常,返回值:" + v);
                    }
                }).exceptionally((e) -> {
                    e.printStackTrace();
                    System.out.println("发生异常情况!");
                    return null;
                });
    }

    private static void future01(ThreadPoolExecutor executor) throws InterruptedException, ExecutionException {


        CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
            System.out.println("runAsync方法无返回值!");
        }, executor);

        CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> {
            return "supplyAsync方法有返回值!";
        }, executor);
        System.out.println("获取返回值:" + supplyAsync.get());
    }
}

/**
 * FutureTake 用于 异步计算和返回值
 * <p>
 * 缺点:
 * 1.get方法会阻塞线程，浪费时间
 * 2.如果有多个线程 线程A 线程B 线程C 线程B依赖与线程A的返回值时,FutureTake不能实现
 */
class MyFutureTake {


    public static void main(String[] args) throws ExecutionException, InterruptedException {

        MyThreadPool myThreadPool = new MyThreadPool();
        ThreadPoolExecutor executor = myThreadPool.getExecutor();

        FutureTask<String> futureTask = new FutureTask<String>(new MyThread03());
        Thread t1 = new Thread(futureTask, "future");
        t1.start();
        //TODO get方法会阻塞线程
        System.out.println("获取返回值:" + futureTask.get());

        System.out.println("---------------------------------------");

        FutureTask<String> task = new FutureTask<>(() -> "MyFutureTake!"
        );
        executor.submit(task);
        System.out.println("获取返回值:" + task.get());

        executor.shutdown();

    }
}

class MyThread01 extends Thread {

    @Override
    public void run() {

    }
}

class MyThread02 implements Runnable {

    @Override
    public void run() {

    }
}

class MyThread03 implements Callable<String> {

    @Override
    public String call() throws Exception {
        return "hello";
    }
}
